package com.red.security;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.red.entity.Account;
import com.red.result.Result;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author: WuShaoJun
 * @create: 2022-09-08 15:09
 **/
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {
    private AuthenticationManager authenticationManager;

    public JWTLoginFilter(AuthenticationManager authenticationManager){
        this.authenticationManager = authenticationManager;
    }

    /**
     * 尝试认证
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            //从requestBody中获取账号和密码
            Account account =
                    new ObjectMapper().readValue(request.getInputStream(), Account.class);
            //判断是哪种账号
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
                    account.getPhone(),
                    account.getPassword(),
                    new ArrayList<>()
            ));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 认证成功
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        String token = null;
        Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
        //权限封装角色集合
        List<String> roleList = new ArrayList();
        for (GrantedAuthority authority : authorities) {
            roleList.add(authority.getAuthority());
        }
        //获取当前时间作为令牌的颁发时间
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        calendar.setTime(now);
        //过期时间
        calendar.add(Calendar.HOUR,24);
        //生成Token
        System.out.println();
        token = Jwts.builder()
                .setSubject(authResult.getName() + "-" + roleList)
                .setIssuedAt(now) //设置颁发时间
                .setExpiration(calendar.getTime()) //设置过期时间
                //.signWith(SignatureAlgorithm.ES512,"security")
                .compact();
        //返回Token
        Map<String,Object> map = new HashMap<>();
        map.put("Authorization", "Bearer " + token);
        //返回正确结果
        Result ok = Result.ok(map);
        response.getWriter().write(JSON.toJSONString(ok));
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        Result ok = Result.error(403,"用户名或密码错误");
        response.getWriter().write(JSON.toJSONString(ok));
    }
}
